package com.serena.da.rest.common;

import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.FileReader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;

/**
 * Created by Spitkovskyi Igor on 7/29/2014.
 */
public class Utils {

    public static String getMD5(String svalue) {
        if (svalue.isEmpty()) {
            System.err.println("No value has been provided for converting to MD5");
            return svalue;
        }

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(svalue.getBytes());
            byte[] digest = md.digest();
            StringBuffer sb = new StringBuffer();
            for (byte b : digest) {
                sb.append(String.format("%02x", b & 0xff));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            System.out.println("Error has occurred on attempt to generate MD5.");
            return svalue + "_WF";
        }
    }

    public static String getTimestamp() {
        return new Timestamp(new Date().getTime()).toString();
    }

    public static String readJsonFromFile(String filePath) {
        String json = "";
        //C:\Users\Administrator\IdeaProjects\RestTest
        //Path currentRelativePath = Paths.get("");
        //String basePath = currentRelativePath.toAbsolutePath().toString();
        String pathToFile = getAbsolutePath(filePath);

        try {
            BufferedReader br = new BufferedReader(new FileReader(pathToFile /*basePath + filePath*/));

            String line;
            while ((line = br.readLine()) != null) {
                json = json + line;
            }
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return json;
    }

    public static String getAbsolutePath(String relativePath) {
        //C:\Users\Administrator\IdeaProjects\RestTest
        Path currentRelativePath = Paths.get("");
        String basePath = currentRelativePath.toAbsolutePath().toString();
        return basePath + relativePath;
    }

    /**
     * replaces dictionary key with value in specified json
     *
     * @param jsonString json string
     * @param hashMap    {{key}} value dictionary
     * @return json string
     */
    public static String replaceJsonStringKeys(String jsonString, HashMap<String, String> hashMap) {
        if (hashMap == null || hashMap.size() == 0) {
            System.out.println("WARN: No hash map provided.");
            return jsonString;
        }

        String nullString = "{{{null}}}";
        String prefix = "{{";
        String suffix = "}}";

        for (String key : hashMap.keySet()) {
            String replaceKey = prefix + key + suffix;
            String value = (key == null) ? nullString : hashMap.get(key);

            jsonString = jsonString.replace(replaceKey, value);
        }

        //avoid having "null" in quotes
        jsonString = jsonString.replace("\"" + nullString + "\"", "null");
        jsonString = jsonString.replace(nullString, "null");

        //warn if there are some not replaced keys.
        if (jsonString.contains(prefix) && jsonString.contains(suffix)) {
            System.out.println("WARN: Some of keys might not have been replaced!");
        }

        return jsonString;
    }

    /**
     * replaces dictionary key with value in specified json
     *
     * @param templateRelativePath json template file name
     * @param hashMap              {{key}} value dictionary
     * @return json string
     */
    public static String replaceJsonTemplateKeys(String templateRelativePath, HashMap<String, String> hashMap) {
        String pathToJsonTemplates = "/json_templates/";
        String jsonString = Utils.readJsonFromFile(pathToJsonTemplates + templateRelativePath);

        return replaceJsonStringKeys(jsonString, hashMap);
    }

    /**
     * @param mergeFromJson
     * @param mergeToJson
     * @return This method takes two JSONObjects and merges them. If JSONObject contains nested JSONObject structures, they will be merged recursively.
     */
    public static JSONObject mergeJSONObjects(JSONObject mergeFromJson, JSONObject mergeToJson) {
        Iterator iterator = mergeFromJson.keys();
        while (iterator.hasNext()) {
            String key = (String) iterator.next();
            Object jsonElement = mergeFromJson.get(key);
            if (jsonElement instanceof JSONObject) {
                mergeJSONObjects((JSONObject) jsonElement, mergeToJson.getJSONObject(key));
                continue;
            }
            mergeToJson.put(key, mergeFromJson.getString(key));
        }
        return mergeToJson;
    }
}
